package tt.dz.order.pojo;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import tt.dz.order.dao.BaseDAOUtil;
import tt.dz.order.exception.BusinessException;
import tt.dz.order.util.AmountUtil;
import tt.dz.order.util.OrderConstant;
import tt.dz.order.util.OrderConstant.AdvancePaymentStage;
import tt.dz.order.util.OrderConstant.OrderPayChannelCode;
import tt.dz.order.util.OrderConstant.OrderPayWay;
import tt.dz.order.util.OrderConstant.OrderStatus;
import tt.dz.order.util.OrderConstant.OrderType;
import tt.dz.order.vo.OrderHistoryQueryVO.OrderHistoryQueryParamVO;
import tt.dz.order.vo.UserPayInfoVO;

/**
 * @Title: 订单基本信息
 * @author zhoutian
 * @date 2015-11-26
 */
public class OrderInfo {
	// 订单号:1位用户类型+3位渠道号+14位当前时间+4位随机数
	private String orderNo;
	// 关联订单编号
	private String relatedOrderNo;
	// 主服务编号,实体服务的父ID
	private String serviceNo;
	// 用户Id
	private String userId;
	// 用户类型； 0 个人客户,1 企业客户,2 支持统付的个人客户
	private String userType;
	// 卡号
	private String cardNo;
	// 卡类型 08 虚拟，06 实体卡  ，07  身份识别卡
	private String cardType;
	// 卡上的余额，如果卡类型是"06 线下卡",需要OMS在第1次调用时传递卡上的余额
	private String payerBalance;
	// 来源系统,用户使用什么app下的单：10001 自主app, 20001 乐视
	private String appId;
	// 匹配的活动规则
	private String activityRule;
	// 实际应付的总价
	private BigDecimal caculatedTotalPrice;
	// 实际付款客户号
	private String realPayer;
	// 实际收款客户号
	private String realReceiver;
	// 支付类型 1 第三方实时支付 2 统付 3 企业支付 4 电子钱包支付 5 代付 6 线下卡
	private Integer payTypeCode;
	// 支付渠道编码,见OrderConstant.OrderPayChannelCode
	private String payChannelCode;
	// 第三方交易流水号
	private String thdPaySeq;
	// 第三方转账金额
	private BigDecimal thdPayAmount;
	// 第三方手续费
	private BigDecimal thdPoundage;
	// 第三方转账完成时间
	private String thdEndTime;
	// 第三方交易状态码
	private String tradeStatusCode;
	// 订单状态
	private Integer status;
	// 创建时间
	private Date createTime;
	// 订单类别(0, "后付款"),(1, "预付款"),若为空，则表示为后付款方式;
	private Integer orderType;
	// 订单阶段:只有预支付类型，才存在支付阶段:(1, "预付款"), (2, "收入"), (3, "差额平衡");
	private Integer stage;
	/**是否被隐藏 是否被用户隐藏,0:未被隐藏,1:已被隐藏*/
	private Integer hide;
	/**订单附加信息*/
	private String attach;

	public String getOrderNo() {
		return orderNo;
	}

	public void setOrderNo(String orderNo) {
		this.orderNo = orderNo;
	}

	public String getRelatedOrderNo() {
		return relatedOrderNo;
	}

	public void setRelatedOrderNo(String relatedOrderNo) {
		this.relatedOrderNo = relatedOrderNo;
	}

	public String getServiceNo() {
		return serviceNo;
	}

	public void setServiceNo(String serviceNo) {
		this.serviceNo = serviceNo;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getUserType() {
		return userType;
	}

	public void setUserType(String userType) {
		this.userType = userType;
	}

	public String getCardNo() {
		return cardNo;
	}

	public void setCardNo(String cardNo) {
		this.cardNo = cardNo;
	}

	public String getCardType() {
		return cardType;
	}

	public void setCardType(String cardType) {
		this.cardType = cardType;
	}

	public String getPayerBalance() {
		return payerBalance;
	}

	public void setPayerBalance(String payerBalance) {
		this.payerBalance = payerBalance;
	}

	public String getAppId() {
		return appId;
	}

	public void setAppId(String appId) {
		this.appId = appId;
	}

	public String getActivityRule() {
		return activityRule;
	}

	public void setActivityRule(String activityRule) {
		this.activityRule = activityRule;
	}

	public BigDecimal getCaculatedTotalPrice() {
		return caculatedTotalPrice;
	}

	public void setCaculatedTotalPrice(BigDecimal caculatedTotalPrice) {
		this.caculatedTotalPrice = caculatedTotalPrice;
	}

	public String getRealPayer() {
		return realPayer;
	}

	public void setRealPayer(String realPayer) {
		this.realPayer = realPayer;
	}

	public String getRealReceiver() {
		return realReceiver;
	}

	public void setRealReceiver(String realReceiver) {
		this.realReceiver = realReceiver;
	}

	public Integer getPayTypeCode() {
		return payTypeCode;
	}

	public void setPayTypeCode(Integer payTypeCode) {
		this.payTypeCode = payTypeCode;
	}

	public String getPayChannelCode() {
		return payChannelCode;
	}

	public void setPayChannelCode(String payChannelCode) {
		this.payChannelCode = payChannelCode;
	}

	public String getThdPaySeq() {
		return thdPaySeq;
	}

	public void setThdPaySeq(String thdPaySeq) {
		this.thdPaySeq = thdPaySeq;
	}

	public BigDecimal getThdPayAmount() {
		return thdPayAmount;
	}

	public void setThdPayAmount(BigDecimal thdPayAmount) {
		this.thdPayAmount = thdPayAmount;
	}

	public BigDecimal getThdPoundage() {
		return thdPoundage;
	}

	public void setThdPoundage(BigDecimal thdPoundage) {
		this.thdPoundage = thdPoundage;
	}

	public String getThdEndTime() {
		return thdEndTime;
	}

	public void setThdEndTime(String thdEndTime) {
		this.thdEndTime = thdEndTime;
	}

	public String getTradeStatusCode() {
		return tradeStatusCode;
	}

	public void setTradeStatusCode(String tradeStatusCode) {
		this.tradeStatusCode = tradeStatusCode;
	}

	public Integer getStatus() {
		return status;
	}

	public void setStatus(Integer status) {
		this.status = status;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public Integer getOrderType() {
		return orderType;
	}

	public void setOrderType(Integer orderType) {
		this.orderType = orderType;
	}

	public Integer getStage() {
		return stage;
	}

	public void setStage(Integer stage) {
		this.stage = stage;
	}

	public Integer getHide() {
		if(hide==null){
			return 0;
		}
		return hide;
	}

	public void setHide(Integer hide) {
		this.hide = hide;
	}

	public String getAttach() {
		return attach;
	}

	public void setAttach(String attach) {
		this.attach = attach;
	}

	public OrderInfo() {
		this.status = OrderStatus.unPay.value();
		this.createTime = new Date();
		this.caculatedTotalPrice = new BigDecimal("0.00");
	}

	private static final String select_all_sql = "select orderNo, relatedOrderNo, serviceNo, userId, userType, cardNo, cardType, payerBalance, appId, activityRule, caculatedTotalPrice, realPayer, realReceiver, payTypeCode, payChannelCode, thdPaySeq, thdPayAmount, thdPoundage, thdEndTime, tradeStatusCode, status, createTime , orderType, stage,hide,attach  from order_info";

	private static final String update_all_sql = "update order_info set orderNo = :orderNo, relatedOrderNo = :relatedOrderNo, serviceNo = :serviceNo, userId = :userId, userType = :userType, cardNo = :cardNo, cardType = :cardType, payerBalance = :payerBalance, appId = :appId, activityRule = :activityRule, caculatedTotalPrice = :caculatedTotalPrice, realPayer = :realPayer, realReceiver = :realReceiver, payTypeCode = :payTypeCode, payChannelCode = :payChannelCode, thdPaySeq = :thdPaySeq, thdPayAmount = :thdPayAmount, thdPoundage = :thdPoundage, thdEndTime = :thdEndTime, tradeStatusCode = :tradeStatusCode, status = :status, createTime = :createTime,orderType=:orderType,stage=:stage,hide=:hide,attach=:attach";

	public void save() {
		String sql = "insert into order_info(orderNo, relatedOrderNo, serviceNo, userId, userType, cardNo, cardType, payerBalance, appId, activityRule, caculatedTotalPrice, realPayer, realReceiver, payTypeCode, payChannelCode, thdPaySeq, thdPayAmount, thdPoundage, thdEndTime, tradeStatusCode, status, createTime,orderType,stage,hide,attach) values(:orderNo, :relatedOrderNo, :serviceNo, :userId, :userType, :cardNo, :cardType, :payerBalance, :appId, :activityRule, :caculatedTotalPrice, :realPayer, :realReceiver, :payTypeCode, :payChannelCode, :thdPaySeq, :thdPayAmount, :thdPoundage, :thdEndTime, :tradeStatusCode, :status, :createTime,:orderType,:stage,:hide,:attach)";
		BaseDAOUtil.updateObject(sql, this);
	}

	public void update() {
		String sql = update_all_sql + " where orderNo = :orderNo";
		BaseDAOUtil.updateObject(sql, this);
	}
	public void updateOrderHide() {
		String sql ="update order_info set hide=:hide where orderNo = :orderNo";
		BaseDAOUtil.updateObject(sql, this);
	}
	public void updateOrderAttach() {
		String sql ="update order_info set attach=:attach where orderNo = :orderNo";
		BaseDAOUtil.updateObject(sql, this);
	}

	/**
	 * 根据订单号查询订单信息
	 * 
	 * @param orderNo
	 *            订单号
	 * @return 订单信息
	 */
	public static OrderInfo getById(String orderNo) {
		String sql = select_all_sql + " where orderNo = :orderNo";
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("orderNo", orderNo);
		return BaseDAOUtil.queryForObject(sql, paramMap, OrderInfo.class);
	}

	/**
	 * 根据关联订单号以及阶段号获取对应的订单 <br>
	 * 关联订单号+阶段,是唯一性的
	 * 
	 * @param relateNo
	 *            关联订单号
	 * @param stage
	 *            阶段
	 * @return
	 */
	public static OrderInfo getOrderByRelateNoAndStage(String relateNo, Integer stage) {
		String sql = select_all_sql + " where relatedOrderNo = :relateNo and stage=:stage ";
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("relateNo", relateNo);
		paramMap.put("stage", stage);
		return BaseDAOUtil.queryForObject(sql, paramMap, OrderInfo.class);
	}
	/**
	 * 根据关联订单号以及阶段号获取对应的订单 <br>
	 * 关联订单号+阶段,是唯一性的
	 * 
	 * @param relateNo
	 *            关联订单号
	 * @param stage
	 *            阶段
	 * @return
	 */
	public static OrderInfo getOrderInfoByOrderNo(String orderNo) {
		String sql = select_all_sql + " where orderNo = :orderNo";
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("orderNo", orderNo);
		return BaseDAOUtil.queryForObject(sql, paramMap, OrderInfo.class);
	}

	/**
	 * 根据多个订单号查询订单列表
	 * 
	 * @param orderIds
	 *            订单号(多个)
	 * @return 订单列表
	 */
	public static List<OrderInfo> getByIds(List<String> orderNos) {
		String sql = select_all_sql + " where orderNo in (:orderNos)";
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("orderNos", orderNos);
		return BaseDAOUtil.queryForList(sql, paramMap, OrderInfo.class);
	}

	/**
	 * 订单历史记录查询
	 * 
	 * @param orderHistoryQueryParamVO
	 *            订单历史记录查询参数
	 * @return 订单列表
	 * @throws BusinessException 
	 */
	public static List<OrderInfo> orderHistoryQuery(OrderHistoryQueryParamVO orderHistoryQueryParamVO) throws BusinessException {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		String sqltr=select_all_sql;
		if(orderHistoryQueryParamVO.getShowAttach()<0||orderHistoryQueryParamVO.getShowAttach()>1){
			throw new BusinessException("订单查询是否显示附加信息参数错误:"+orderHistoryQueryParamVO.getShowAttach());
		}
		if(orderHistoryQueryParamVO.getShowAttach()==0){
			sqltr=sqltr.replace(",attach", "");
		}
		StringBuilder sql = new StringBuilder(sqltr);
		String condition = orderHistoryQueryParamVO.getCondition();
		Date startTime = orderHistoryQueryParamVO.getStartTime();
		Date endTime = orderHistoryQueryParamVO.getEndTime();
		Integer pageNo = orderHistoryQueryParamVO.getPageNo();
		Integer pageSize = orderHistoryQueryParamVO.getPageSize();
		Integer orderStatus = orderHistoryQueryParamVO.getOrderStatus();
		sql.append(" where userId = :userId");
		paramMap.put("userId", orderHistoryQueryParamVO.getUserId());
		if (orderStatus != null) {
			sql.append(" and status = :status");
			paramMap.put("status", orderHistoryQueryParamVO.getOrderStatus());
		}
		if (condition.equals("1") || condition.equals("3")) {
			sql.append(" and createTime >= :startTime");
			sql.append(" and createTime <= :endTime");
			paramMap.put("startTime", startTime);
			paramMap.put("endTime", endTime);
		}
		if(orderHistoryQueryParamVO.getShowHide()<0||orderHistoryQueryParamVO.getShowHide()>1){
			throw new BusinessException("订单查询是否显示隐藏订单参数错误:"+orderHistoryQueryParamVO.getShowHide());
		}
		if(1!=orderHistoryQueryParamVO.getShowHide()){
			sql.append(" and hide = :hide");
			paramMap.put("hide", 0);
		}
		sql.append(" order by createTime desc");
		if (condition.equals("2") || condition.equals("3")) {
			sql.append(" limit :limit offset :offset");
			paramMap.put("limit", pageSize);
			paramMap.put("offset", (pageNo - 1) * pageSize);
		}
		
		return BaseDAOUtil.queryForList(sql.toString(), paramMap, OrderInfo.class);
	}

	/**
	 * 查询某用户需要支付的订单
	 * 
	 * @param orderHistoryQueryParamVO
	 *            订单历史记录查询参数
	 * @return 订单列表
	 */
	public static List<OrderInfo> findUserNeedPayOrders(String userId) {
		String notNullSql = select_all_sql + " where userId = :userId and (payTypeCode !=  " + OrderPayWay.unify.value()
				+ " and payTypeCode != " + OrderPayWay.enterprise.value() + ")  and status = "
				+ OrderStatus.unPay.value();
		// null 不参与运算比较，则另外考虑
		String nullSql = select_all_sql + " where userId = :userId and  payTypeCode is null   and status = "
				+ OrderStatus.unPay.value();

		String sql = notNullSql + "   UNION	 " + nullSql;

		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("userId", userId);
		return BaseDAOUtil.queryForList(sql, paramMap, OrderInfo.class);
	}

	/**
	 * 根据订单号修改订单状态
	 * 
	 * @param orderNos
	 *            订单号的列表
	 * @param status
	 *            订单状态
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void changeOrderStatus(List<String> orderNos, int status) {
		String sql = "update order_info set status = :status where orderNo = :orderNo";
		Map[] batchValues = new HashMap[orderNos.size()];
		for (int i = 0; i < orderNos.size(); i++) {
			String orderNo = orderNos.get(i);
			Map<String, Object> paramMap = new HashMap<String, Object>();
			paramMap.put("status", status);
			paramMap.put("orderNo", orderNo);
			batchValues[i] = paramMap;
		}
		BaseDAOUtil.batchUpdate(sql, batchValues);
	}

	/**
	 * 用户发起支付时修改订单支付信息
	 * 
	 * @param userPayInfoVO
	 *            用户支付信息
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void updateOrderOnPaying(UserPayInfoVO userPayInfoVO) {
		String sql = "update order_info set status = :status, realPayer = :realPayer, payTypeCode = :payTypeCode, payChannelCode = :payChannelCode where orderNo = :orderNo";
		Map paramMap = new HashMap();
		paramMap.put("realPayer", userPayInfoVO.getPayer());
		paramMap.put("payTypeCode", userPayInfoVO.getPayTypeCode());
		if (userPayInfoVO.getPayTypeCode() == OrderPayWay.unify.value()
				|| userPayInfoVO.getPayTypeCode() == OrderPayWay.enterprise.value()) {
			paramMap.put("status", OrderStatus.unPay.value());
		} else if (userPayInfoVO.getPayTypeCode() == OrderPayWay.electronicPurse.value()) {
			paramMap.put("status", OrderStatus.payedDone.value());
		} else {
			paramMap.put("status", OrderStatus.paying.value());
		}
		paramMap.put("payChannelCode", userPayInfoVO.getPayChannelCode());
		paramMap.put("orderNo", userPayInfoVO.getOrderNo());
		BaseDAOUtil.update(sql, paramMap);
	}

	/**
	 * 收到有贝先付回调时修改订单支付信息
	 * 
	 * @param userPayInfoVO
	 *            用户支付信息
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void updateOrderAfterYouBeiPayBack(YouBeiPayCallBackRecord youBeiPayCallBackRecord) {
		String sql = "update order_info set payChannelCode=:payChannelCode,  payTypeCode =:payTypeCode,   status = :status, thdPaySeq = :thdPaySeq, thdPayAmount = :thdPayAmount, thdPoundage = :thdPoundage, thdEndTime = :thdEndTime, tradeStatusCode = :tradeStatusCode where orderNo = :orderNo";
		Map paramMap = new HashMap();
		paramMap.put("status", OrderStatus.payedDone.value());
		paramMap.put("thdPaySeq", youBeiPayCallBackRecord.getTradeNo());
		paramMap.put("thdPayAmount", youBeiPayCallBackRecord.getTotalFee());
		paramMap.put("thdPoundage", new BigDecimal("0.00"));
		paramMap.put("thdEndTime", youBeiPayCallBackRecord.getGmtPayment());
		paramMap.put("tradeStatusCode", youBeiPayCallBackRecord.getTradeStatus());
		paramMap.put("orderNo", youBeiPayCallBackRecord.getOrderNo());
		// 当前已经确认了是第三发支付方式
		paramMap.put("payTypeCode", OrderConstant.OrderPayWay.thirdImmediately.value());
		// 支付渠道已经确认了是优贝支付方式，payChannelCode
		paramMap.put("payChannelCode", OrderConstant.OrderPayChannelCode.youbeipay.value());
		BaseDAOUtil.update(sql, paramMap);
	}

	/**
	 * 收到支付宝支付回调时修改订单支付信息
	 * 
	 * @param userPayInfoVO
	 *            用户支付信息
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void updateOrderAfterALiPayBack(AliPayCallBackRecord aliPayCallBackRecord) {
		String sql = "update order_info set  payChannelCode=:payChannelCode,  payTypeCode =:payTypeCode, status = :status, thdPaySeq = :thdPaySeq, thdPayAmount = :thdPayAmount, thdPoundage = :thdPoundage, thdEndTime = :thdEndTime, tradeStatusCode = :tradeStatusCode where orderNo = :orderNo";
		Map paramMap = new HashMap();
		paramMap.put("status", OrderStatus.payedDone.value());
		paramMap.put("thdPaySeq", aliPayCallBackRecord.getTradeNo());
		paramMap.put("thdPayAmount", new BigDecimal(aliPayCallBackRecord.getTotalFee()));
		paramMap.put("thdPoundage", new BigDecimal("0.00"));
		paramMap.put("thdEndTime", aliPayCallBackRecord.getGmtPayment());
		paramMap.put("tradeStatusCode", aliPayCallBackRecord.getTradeStatus());
		paramMap.put("orderNo", aliPayCallBackRecord.getOrderNo());
		// 当前已经确认了是第三发支付方式
		paramMap.put("payTypeCode", OrderConstant.OrderPayWay.thirdImmediately.value());
		// 支付渠道已经确认了是支付宝支付方式，payChannelCode
		paramMap.put("payChannelCode", OrderConstant.OrderPayChannelCode.alipay.value());
		BaseDAOUtil.update(sql, paramMap);
		postPayBackService(OrderPayChannelCode.alipay, OrderPayWay.thirdImmediately, aliPayCallBackRecord.getOrderNo(),
				true);
	}

	/**
	 * 调用外部支付方式的回调接口服务的后置处理服务<br>
	 * 当前业务逻辑：处理预付款订单类型，并且对差额平衡阶段的时候，支付成功的时候，对收入阶段的订单保存支付状态进行相关更新<br>
	 * 并且进行台帐创建
	 * 
	 * @param code
	 *            当前前支付渠道
	 * @param payway
	 *            当前支付方式
	 * @param curOrderNo
	 *            当前支付的订单号
	 * 
	 * @param isPaySuccess
	 *            是否支付成功
	 */
	public static void postPayBackService(OrderPayChannelCode code, OrderPayWay payway, String curOrderNo,
			boolean isPaySuccess) {
		// 根据不同的订单类型，处理不同的操作
		if (StringUtils.isEmpty(curOrderNo)) {
			return;
		}
		OrderInfo curOrderInfo = OrderInfo.getById(curOrderNo);
		if (curOrderInfo == null) {
			return;
		}
		OrderType orderType = OrderInfo.getOrderInfoType(curOrderInfo);
		switch (orderType) {
		case ADVANCE_PAYMENT:
			// 支付状态为预支付状态
			AdvancePaymentStage stage = AdvancePaymentStage.valueOfByInt(curOrderInfo.getStage());
			switch (stage) {
			case BALANCE_ALLOWANCE:
				// 若当前的阶段为差额平衡阶段
				// 根据不同类型的差额
				String relateOrderNo = curOrderInfo.getRelatedOrderNo();
				OrderInfo incomeOrder = OrderInfo.getOrderByRelateNoAndStage(relateOrderNo,
						AdvancePaymentStage.INCOME.value());
				if (incomeOrder == null) {
					return;
				}
				if (isPaySuccess) {
					// 支付成功的时候，修改收入阶段的订单支付状态
					// 以及当前台帐状态创建
					incomeOrder.setStatus(OrderStatus.payedDone.value());
					incomeOrder.update();
					OrderAccountingStatus.generatOrderAccountingStatus(relateOrderNo, true);
				}

				break;

			default:

				break;
			}

			break;

		default:
			break;
		}
	}

	/**
	 * 收到微信支付回调时修改订单支付信息
	 * 
	 * @param userPayInfoVO
	 *            用户支付信息
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void updateOrderAfterWeiXinPayBack(WeiXinPayCallBackRecord weixinPayCallBackRecord) {
		String sql = "update order_info set  payChannelCode=:payChannelCode,  payTypeCode =:payTypeCode,  status = :status, thdPaySeq = :thdPaySeq, thdPayAmount = :thdPayAmount, thdPoundage = :thdPoundage, thdEndTime = :thdEndTime, tradeStatusCode = :tradeStatusCode where orderNo = :orderNo";
		Map paramMap = new HashMap();
		paramMap.put("status", OrderStatus.payedDone.value());
		paramMap.put("thdPaySeq", weixinPayCallBackRecord.getTradeNo());
		// 微信支付回调的totalFee单位为分，需要转化为元
		paramMap.put("thdPayAmount",
				AmountUtil.divide(new BigDecimal(weixinPayCallBackRecord.getTotalFee()), new BigDecimal("100")));
		paramMap.put("thdPoundage", new BigDecimal("0.00"));
		paramMap.put("thdEndTime", weixinPayCallBackRecord.getTimeEnd());
		paramMap.put("tradeStatusCode", weixinPayCallBackRecord.getResultCode());
		paramMap.put("orderNo", weixinPayCallBackRecord.getOrderNo());
		// 当前已经确认了是第三发支付方式
		paramMap.put("payTypeCode", OrderConstant.OrderPayWay.thirdImmediately.value());
		// 支付渠道已经确认了是微信支付方式，payChannelCode
		paramMap.put("payChannelCode", OrderConstant.OrderPayChannelCode.weixinpay.value());
		BaseDAOUtil.update(sql, paramMap);
	}

	/**
	 * 根据订单获取当前订单类型
	 * 
	 * @param orderNo
	 * @return
	 */
	public static OrderType getOrderInfoType(String orderNo) {
		if (StringUtils.isEmpty(orderNo)) {
			return null;
		}
		OrderInfo order = OrderInfo.getById(orderNo);
		return OrderInfo.getOrderInfoType(order);
	}

	/**
	 * 获取最小订单创建时间
	 * 
	 * @return
	 */
	public static String queryMinCreateTime() {
		String sql="SELECT to_char(min(createtime),'YYYY-MM') as createtime from order_info";
		List<Map<String, Object>> list = BaseDAOUtil.queryForList(sql, null);
		if (CollectionUtils.isEmpty(list)) {
			return null;
		} else {
			return list.get(0).get("createtime").toString();
		}
	}

	/**
	 * 根据订单获取当前订单类型
	 * 
	 * @param order
	 * @return
	 */
	public static OrderType getOrderInfoType(OrderInfo order) {
		if (order == null) {
			return null;
		}
		Integer orderType = order.getOrderType();
		if (orderType == null) {
			return OrderType.AFTER_PAYMENT;
		}
		return OrderType.indexOf(orderType);
	}

	/**
	 * 断言当前是某种订单类型
	 * 
	 * @param orderInfo
	 *            当前订单
	 * @param type
	 *            断言的订单类型
	 * @return
	 */
	public static boolean assertOrderType(OrderInfo orderInfo, OrderType type) {
		return type == getOrderInfoType(orderInfo);
	}

	/**
	 * 断言预付款订单当前订单阶段
	 * 
	 * @param orderInfo
	 *            当前订单
	 * @param stage
	 *            当前订单阶段
	 * @return
	 */
	public static boolean assertAdvanceStage(OrderInfo orderInfo, AdvancePaymentStage stage) {
		return orderInfo != null && assertOrderType(orderInfo, OrderType.ADVANCE_PAYMENT)
				&& stage == AdvancePaymentStage.valueOfByInt(orderInfo.getStage());
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("OrderInfo [orderNo=");
		builder.append(orderNo);
		builder.append(", relatedOrderNo=");
		builder.append(relatedOrderNo);
		builder.append(", serviceNo=");
		builder.append(serviceNo);
		builder.append(", userId=");
		builder.append(userId);
		builder.append(", userType=");
		builder.append(userType);
		builder.append(", cardNo=");
		builder.append(cardNo);
		builder.append(", cardType=");
		builder.append(cardType);
		builder.append(", payerBalance=");
		builder.append(payerBalance);
		builder.append(", appId=");
		builder.append(appId);
		builder.append(", activityRule=");
		builder.append(activityRule);
		builder.append(", caculatedTotalPrice=");
		builder.append(caculatedTotalPrice);
		builder.append(", realPayer=");
		builder.append(realPayer);
		builder.append(", realReceiver=");
		builder.append(realReceiver);
		builder.append(", payTypeCode=");
		builder.append(payTypeCode);
		builder.append(", payChannelCode=");
		builder.append(payChannelCode);
		builder.append(", thdPaySeq=");
		builder.append(thdPaySeq);
		builder.append(", thdPayAmount=");
		builder.append(thdPayAmount);
		builder.append(", thdPoundage=");
		builder.append(thdPoundage);
		builder.append(", thdEndTime=");
		builder.append(thdEndTime);
		builder.append(", tradeStatusCode=");
		builder.append(tradeStatusCode);
		builder.append(", status=");
		builder.append(status);
		builder.append(", createTime=");
		builder.append(createTime);
		builder.append(", orderType=");
		builder.append(orderType);
		builder.append(", stage=");
		builder.append(stage);
		builder.append("]");
		return builder.toString();
	}
	
}
